#!/usr/bin/python2
# Distributed under the terms of the GNU General Public License v2
# The original bash version of autorun was developed by Pierre Dorgueil in 2003
# The current python implementation has been developed by Francois Dupoux in 2008
# ----------------------- changeslog: -----------------------------------------
# 2003-10-01: Pierre Dorgueil --> original bash version of autorun for sysresccd
# 2008-01-26: Francois Dupoux --> rewrote autorun in python to support http
# 2008-01-27: Francois Dupoux --> added 'ar_ignorefail', 'ar_nodel', 'ar_disable'
# 
# ----------------------- autorun exec rules: --------------------------------- 
# - pass 'ar_source=/dev/fd#' to request floppy device test
# - CD is tested if no floppy requested or no autorun found on floppy
# - if a file named 'autorun' is found on any media, it is always run, except if
#   option 'ar_disable' is used
# - if a file named 'autorun[0-9]' is found on any media, it is run if either
#      - 'autoruns=...' arg did specify its number (ex. autoruns=1,3,5), or
#      - no 'autoruns=...' arg was passed
# - pass autoruns=no to prevent running any 'autorun[0-9A-F]' file
# - defaults to allow all 'autorun[0-9A-F]' files
# - if many autorun files are to be run,
#      - always in alphab order: autorun, then autorun0, then autorun1 etc...
#      - first non-zero exit code stops all (except if ar_ignorefail is used)
# - if option 'ar_nodel' is used, the temp copy of the script will not be deleted
# - if option 'ar_ignorefail' is used, do not stop autorun if a script failed
# - if option 'ar_disable' is used, absolutely no autorun script will be run

import sys, os, commands, re

# ----------------------- autorun default parameters --------------------------
pidfile='/run/autorun.pid'
basedir='/var/autorun'
autorunlog=basedir+'/log'
autorunmnt=basedir+'/mnt'
autoruntmp=basedir+'/tmp'
defaultsrc=['/livemnt/boot','/var/autorun/cdrom','/root','/usr/share/sys.autorun']
ar_autoruns=['']+list('0123456789ABCDEF')
cmdline=file('/proc/cmdline').read()
autorunfiles=[]
ar_nowait='n'
ar_nodel='n'
ar_ignorefail='n'
ar_source=''

# ----------------------- functions definitions -------------------------------
def processdostextfiles(curfile): # remove all '\r' in that file
	txt=file(curfile).read().replace('\r','')
	txtfile=file(curfile, 'wb')
	txtfile.write(txt)
	txtfile.close()

def printtitle(title, padding):
	totallen=80	
	startpos=int(totallen/2)-int(len(title)/2)
	remain=totallen-startpos-len(title)
	text=(padding*startpos)+title+(padding*remain)
	print text

def copyfilefct_basic(src, dest):
	if os.path.isfile(src):
		dstfile=file(dest, 'wb')
		dstfile.write(file(src).read())
		dstfile.close()
		os.chmod(dest, 755)
		return 0
	else:
		return -1

def copyfilefct_http(src, dest):
	cmd="wget %s -O %s"%(src, dest)
	(status, output)=commands.getstatusoutput(cmd)
	if status==0:
		os.chmod(dest, 755)
		return 0
	else:
		os.unlink(dest)
		return -1

def search_autoruns(dirname, ar_autoruns, copyfilefct):
	found=0
	for ext in ar_autoruns:
		curpath=os.path.join(dirname, 'autorun%s'%ext)
		newpath=os.path.join(autoruntmp, 'autorun%s'%ext)
		if copyfilefct(curpath, newpath)==0:
			autorunfiles.append(newpath)
			found+=1
	return found

def main():
	global ar_nowait, ar_nodel, ar_ignorefail, ar_source, ar_autoruns
	status=0 # in case no autorun executed
	print 'Initializing autorun...\n'
	
	# ---- brutal kernel args parsing ----
	for opt in cmdline.split():
		if re.match('^subdir=', opt):
			param=opt.replace('subdir=','')
			defaultsrc.insert(0, '/livemnt/boot/' + param)
		if re.match('^ar_nowait$', opt):
			ar_nowait='y'
		if re.match('^ar_nodel$', opt):
			ar_nodel='y'
		if re.match('^ar_ignorefail$', opt):
			ar_ignorefail='y'
		if re.match('^ar_disable$', opt):
			ar_autoruns=[]
		if re.match('^ar_source=', opt):
			param=opt.replace('ar_source=','')
			ar_source=param
		if re.match('^autoruns=', opt):
			param=opt.replace('autoruns=','')
			if param=='no':
				ar_autoruns=['']
			else:
				ar_autoruns=['']+param.split(',')
		
	if len(ar_autoruns)==0: # nothing to do
		sys.exit(0)

	# ---- parse the autorun sources ----
	if re.match('^http://', ar_source):
		search_autoruns(ar_source, ar_autoruns, copyfilefct_http)
	elif re.match('^/dev/', ar_source): # mount a partition/device
		mnt1='mount %s %s'%(ar_source, autorunmnt)
		mnt2='umount %s'%autorunmnt
		(status, output)=commands.getstatusoutput(mnt1)
		if status!=0:
			print 'fatal error: cannot mount (%s)'%mnt1
			sys.exit(1)
    		search_autoruns(autorunmnt, ar_autoruns, copyfilefct_basic)
		commands.getstatusoutput(mnt2)
	elif re.match('^nfs://', ar_source): # mount an nfs share
		source=ar_source.replace('nfs://','')
		mnt1='mount -t nfs -o nolock %s %s'%(source, autorunmnt)
		mnt2='umount %s'%autorunmnt
		(status, output)=commands.getstatusoutput(mnt1)
		if status!=0:
			print 'fatal error: cannot mount (%s)'%mnt1
			sys.exit(1)
    		search_autoruns(autorunmnt, ar_autoruns, copyfilefct_basic)
		commands.getstatusoutput(mnt2)
	elif re.match('^smb://', ar_source): # mount a samba share
		source=ar_source.replace('smb://','')
		mnt1='mount -t cifs //%s %s'%(source, autorunmnt)
		mnt2='umount %s'%autorunmnt
		(status, output)=commands.getstatusoutput(mnt1)
		if status!=0:
			print 'fatal error: cannot mount (%s)'%mnt1
			sys.exit(1)
    		search_autoruns(autorunmnt, ar_autoruns, copyfilefct_basic)
		commands.getstatusoutput(mnt2)
	else: # search in all the default directories
		if ar_source!='':
			print 'cannot find a valid ar_source, searching scripts in the default directories'
		found=0
		for curdir in defaultsrc:
			if found==0:
				found+=search_autoruns(curdir, ar_autoruns, copyfilefct_basic)

	# ---- remove user setable ar_nowait flag if set ----
	if os.path.isfile('/etc/ar_nowait'):
		os.unlink('/etc/ar_nowait')

	# ---- execute the autorun scripts found ----
	for curfile in autorunfiles:
		processdostextfiles(curfile)
		filebase=os.path.basename(curfile)
		redir=os.path.join(autorunlog, filebase)
		cmd='sh %s 2>&1 | tee %s'%(curfile, redir)
		print '\n'; printtitle('executing %s'%filebase, '=')
		status=os.system(cmd)
		fileres=open(redir+'.return','wb')
		fileres.write(str(status)+'\n')
		fileres.close()
		print '\n'+'='*80+'\n'
		
		# first non zero exit stops all
		if status!=0 and ar_ignorefail=='n':
			print 'execution of %s returned %d: aborting autorun'%(filebase,status)
			ar_nowait='y'
			break;
		
	# ---- delete the copies of the scripts ----
	if ar_nodel=='n':
		for curfile in autorunfiles:
			print 'removing %s'%curfile
			os.unlink(curfile)
	
	# ---- wait a keypress feature -----
	if os.path.isfile('/etc/ar_nowait'):
		ar_nowait='y'
	if ar_nowait=='n' and len(autorunfiles)>0:
		print 'end of autorun scripts, press <Enter> to continue'
		sys.stdin.read(1)

	return status

# ----------------------- autorun main ----------------------------------------
# run autorun only one time (tty1)
#(status, output) = commands.getstatusoutput('tty')
#if status!=0: sys.exit(1)
#if output not in ('/dev/tty1', '/dev/ttyS0', '/dev/ttyS1') : sys.exit(1)

# mkdir /var/autorun, logdir
for curdir in (basedir, autorunlog, autorunmnt, autoruntmp):
	if not os.path.isdir(curdir):
		os.mkdir(curdir)

# exit if already done
if os.path.isfile(pidfile): sys.exit(0)

# create lockfile 
lockfile=open(pidfile, 'wb')
lockfile.write(str(os.getpid()))

try:
	res=main()
	sys.exit(res)
finally:
	os.unlink(pidfile)
